# coding: utf-8
from __future__ import unicode_literals

import re
import datetime
from decimal import Decimal

import xlrd

from common.constant import DATE_FORMAT, EMAIL_FORMAT, PHONE_FORMAT
from common.exceptions import ImportFieldError


def error_msg_handler(schema, self):
    """
    create by ld_wu 2017-04-12
    :return:
    """
    def wrapper(func):
        def catch_import_error(*args, **kwargs):
            try:
                return func(*args,  **kwargs)
            except ImportFieldError as e:
                schema.error_msg.add(
                    (self.row_num, self.msg_format % e)
                )
        return catch_import_error

    return wrapper


class ImportField(object):
    """
    create by ld_wu 2017-04-07
    导入字段类型定义
    """

    field_name = ''

    def __init__(self, index, required=False, label_name='',
                 encode_func=None, default=None):
        self.index = index
        self.required = required
        self.row_num = 0
        self.label_name = label_name
        self.msg_format = self.__gen_msg_format()
        self.encode_func = encode_func
        self.default = default

    def _serialize(self, value):
        return value

    def __check_required(self, value):
        """
        create by ld_wu 2017-04-07
        验证是否为空
        """
        if self.required and not value:
            raise ImportFieldError('不能为空')

    def __gen_msg_format(self):
        """
        create by ld_wu 2017-04-07
        """

        msg_format = ('{}%s' if self.label_name else '第{}列%s')

        msg = msg_format.format((self.label_name or self.index + 1))
        return msg

    def validate(self, value):
        pass

    def raw_value(self, instance):
        return instance.sheet.cell(instance.row, self.index).value

    def __get__(self, instance, owner):
        self.row_num = instance.row + 1
        raw_value = self.raw_value(instance)
        raw_value = self.default if raw_value is None else raw_value
        if self.encode_func:
            raw_value = self.encode_func(raw_value)

        schema_error_func = error_msg_handler(instance, self)

        value = schema_error_func(self._serialize)(raw_value)
        schema_error_func(self.__check_required)(value)
        validators = instance.validators.get(self.field_name)
        if validators:
            map(lambda x: schema_error_func(x)(instance, value), validators)

        schema_error_func(self.validate)(value)
        # 缓存作用
        setattr(instance, self.field_name, value)
        return value


class PhoneField(ImportField):
    """
    create by ld_wu 2017-04-07
    手机类型
    """

    def _serialize(self, value):
        return str(value).strip().split('.')[0]

    def validate(self, value):
        if re.match(PHONE_FORMAT, value) is None:
            raise ImportFieldError('格式不对')


class FloatField(ImportField):
    """
    create by ld_wu 2017-04-07
    浮点型
    """

    def _serialize(self, value):
        try:
            return float(value)
        except (ValueError, TypeError):
            raise ImportFieldError('格式不对')


class DecimalField(ImportField):

    def _serialize(self, value):
        try:
            return Decimal(value)
        except (ValueError, TypeError):
            raise ImportFieldError('格式不对')


class StrField(ImportField):
    """
    create by ld_wu 2017-04-07
    字符串
    """

    def _serialize(self, value):
        try:
            return str(value).strip().replace(' ', '')
        except (ValueError, TypeError):
            raise ImportFieldError('格式不对')


class ComplexField(ImportField):

    def __init__(self, start, end, *args, **kwargs):
        self.end = end
        super(ComplexField, self).__init__(start, *args, **kwargs)

    def raw_value(self, instance):
        return map(
            lambda x: instance.sheet.cell(instance.row, x).value,
            range(self.index, self.end)
        )


class BoolField(ImportField):
    """
    create by ld_wu 2017-04-15
    bool类型
    """

    def _serialize(self, value):
        if value in (True, '是', 'True', 'true'):
            return True
        return False


class EmailField(ImportField):
    """
    create by ld_wu 2017-04-15
    邮箱类型
    """

    def validate(self, value):
        if re.match(EMAIL_FORMAT, value) is None:
            raise ImportFieldError('格式不对')


class DateField(ImportField):
    """
    create by ld_wu 2017-04-15
    日期类型
    """

    def _serialize(self, value):
        try:
            if isinstance(value, (int, float)):
                return xlrd.xldate.xldate_as_datetime(int(value), 0)
            elif isinstance(value, str):
                return datetime.datetime.strptime(value.strip(), DATE_FORMAT)
        except (ValueError, TypeError):
            return None


class NestedField(object):

    def __init__(self, schema_cls):
        self.schema_cls = schema_cls

    def __get__(self, instance, owner):
        schema = self.schema_cls(
            instance.sheet, instance.row, instance.error_msg
        )
        return schema


class IntField(ImportField):
    """
    create by ld_wu 2017-04-07
    整型
    """

    def _serialize(self, value):
        try:
            return int(value)
        except (ValueError, TypeError):
            raise ImportFieldError('格式不对')
